package com.sinsz.wxpn.open.base.impl;

import com.fcibook.quick.http.QuickHttp;
import com.fcibook.quick.http.ResponseBody;
import com.sinsz.wxpn.exception.WxpnException;
import com.sinsz.wxpn.open.BaseWxpn;
import com.sinsz.wxpn.open.base.BaseService;
import com.sinsz.wxpn.open.base.support.MaterialCreateType;
import com.sinsz.wxpn.open.base.support.MaterialType;
import com.sinsz.wxpn.open.support.FormaterUtils;
import com.sinsz.wxpn.properties.WxpnProperties;
import com.sinsz.wxpn.support.Constant;
import org.apache.commons.lang3.StringUtils;
import org.nutz.http.Header;
import org.nutz.http.Http;
import org.nutz.http.Request;
import org.nutz.http.Response;
import org.nutz.http.sender.FilePostSender;
import org.nutz.json.Json;
import org.nutz.json.JsonFormat;
import org.springframework.http.MediaType;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * 基本接口实现
 * @author chenjianbo
 * @date 2018-11-12
 */
public class BaseServiceImpl extends BaseWxpn implements BaseService {

    private HttpServletResponse httpResponse;

    public BaseServiceImpl(WxpnProperties prop, HttpServletResponse httpResponse) {
        super(prop);
        this.httpResponse = httpResponse;
    }

    @Override
    public boolean oauthSignatureComparison(String openid, String tag, String timestamp, String sign) {
        openid = StringUtils.isEmpty(openid) ? "" : openid;
        tag = StringUtils.isEmpty(tag) ? "" : tag;
        timestamp = StringUtils.isEmpty(timestamp) ? "" : timestamp;
        if (StringUtils.isEmpty(sign)) {
            return false;
        }
        String newSign = FormaterUtils.signatureSha1(openid + tag + timestamp + super.prop().getAppSecret());
        return !StringUtils.isEmpty(newSign) && sign.equals(newSign);
    }

    @Override
    public String fetchToken() {
        Map<String, String> map = new HashMap<>(0);
        map.put("grant_type", Constant.GRANT_TYPE);
        map.put("appid", super.prop().getAppId());
        map.put("secret", super.prop().getAppSecret());
        try {
            ResponseBody response = new QuickHttp().addParames(map).url(Constant.ACCESS_TOKEN).get().setConnectionTimeout(Constant.TIME_OUT).body();
            return FormaterUtils.defaultFormat(response.text());
        } catch (Exception e) {
            e.printStackTrace(System.out);
            throw new WxpnException("接口请求异常.");
        }
    }

    @Override
    public String fetchCallbackIP(String token) {
        if (StringUtils.isEmpty(token)) {
            throw new WxpnException("用户授权Token不能为空");
        }
        Map<String, String> map = new HashMap<>(0);
        map.put("access_token", token);
        try {
            ResponseBody response = new QuickHttp().addParames(map).url(Constant.CALLBACK_IP).get().setConnectionTimeout(Constant.TIME_OUT).body();
            return FormaterUtils.defaultFormat(response.text());
        } catch (Exception e) {
            e.printStackTrace(System.out);
            throw new WxpnException("接口请求异常.");
        }
    }

    @Override
    public String fetchCheckIP(String token) {
        if (StringUtils.isEmpty(token)) {
            throw new WxpnException("用户授权Token不能为空");
        }
        Map<String, String> map = new HashMap<>(0);
        map.put("action", Constant.CHECK_ACTION);
        map.put("check_operator", Constant.CHECK_OPERATOR);
        try {
            Response response = Http.post3(Constant.IP_CHECK + token, Json.toJson(map, JsonFormat.tidy()), Header.create().set("Content-Type", "application/json"), Constant.TIME_OUT, Constant.TIME_OUT);
            if (response.isOK()) {
                return FormaterUtils.defaultFormat(response.getContent("UTF-8"));
            } else {
                throw new WxpnException(Json.toJson(response, JsonFormat.tidy()));
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
            throw new WxpnException("接口请求异常.");
        }
    }

    @Override
    public String fetchMaterialList(String token, MaterialType material, int offset) {
        if (StringUtils.isEmpty(token)) {
            throw new WxpnException("用户授权Token不能为空");
        }
        material = material == null ? MaterialType.NEWS : material;
        Map<String, Object> map = new HashMap<>(0);
        map.put("type", material.name().toLowerCase());
        map.put("offset", Math.abs(offset));
        map.put("count", 20);
        try {
            Response response = Http.post3(Constant.BATCHGET_MATERIAL + token, Json.toJson(map, JsonFormat.tidy()), Header.create().set("Content-Type", "application/json"), Constant.TIME_OUT, Constant.TIME_OUT);
            if (response.isOK()) {
                return FormaterUtils.defaultFormat(response.getContent("UTF-8"));
            } else {
                throw new WxpnException(Json.toJson(response, JsonFormat.tidy()));
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
            throw new WxpnException("接口请求异常.");
        }
    }

    @Override
    public String createMaterial(String token, MaterialCreateType material, String title, String introduction, String filePath) {
        if (StringUtils.isEmpty(filePath)) {
            throw new WxpnException("上传文件不能为空");
        }
        File media = new File(filePath);
        return createMaterial(token, material, title, introduction, media);
    }

    @Override
    public String createMaterial(String token, MaterialCreateType material, String title, String introduction, File media) {
        if (StringUtils.isEmpty(token)) {
            throw new WxpnException("用户授权Token不能为空");
        }
        if (material == null) {
            throw new WxpnException("需指定上传素材类型");
        }
        if (material == MaterialCreateType.VIDEO) {
            title = StringUtils.isEmpty(title) ? "暂无标题": title;
            introduction = StringUtils.isEmpty(introduction) ? "暂无描述": introduction;
        }
        if (media == null || media.isDirectory() || !media.exists()) {
            throw new WxpnException("上传文件不能为空");
        }
        Map<String, Object> map = new HashMap<>(0);
        map.put("title", title);
        map.put("introduction", introduction);
        Map<String, Object> param = new HashMap<>(0);
        map.put("description", Json.toJson(map, JsonFormat.tidy()));
        try {
            Request req = Request.create(Constant.ADD_MATERIAL + token + "&type=" + material.name().toLowerCase(), Request.METHOD.POST, Json.toJson(param, JsonFormat.tidy()));
            req.getParams().put("media", media);
            FilePostSender sender = new FilePostSender(req);
            Response response = sender.send();
            if (response.isOK()) {
                return FormaterUtils.defaultFormat(response.getContent("UTF-8"));
            } else {
                throw new WxpnException(Json.toJson(response, JsonFormat.tidy()));
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
            throw new WxpnException("接口请求异常.");
        }
    }

    @Override
    public String fetchMaterialByMediaId(String token, String mediaId) {
        if (StringUtils.isEmpty(token)) {
            throw new WxpnException("用户授权Token不能为空");
        }
        if (StringUtils.isEmpty(mediaId)) {
            throw new WxpnException("素材媒体ID不能为空");
        }
        Map<String, Object> map = new HashMap<>(0);
        map.put("media_id", mediaId);
        try {
            Response response = Http.post3(Constant.GET_MATERIAL + token, Json.toJson(map, JsonFormat.tidy()), Header.create().set("Content-Type", "application/json"), Constant.TIME_OUT, Constant.TIME_OUT);
            if (response.isOK()) {
                String contentType = response.getHeader().get("Content-Type");
                if (MediaType.TEXT_PLAIN_VALUE.equalsIgnoreCase(contentType)) {
                    return FormaterUtils.defaultFormat(response.getContent("UTF-8"));
                } else if (response.getHeader().get("Content-Type") == null){
                    httpResponse.setHeader("Content-Type", MediaType.APPLICATION_OCTET_STREAM_VALUE + ";charset=UTF-8");
                    httpResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
                    httpResponse.setHeader("Connection", "keep-alive");
                    httpResponse.setHeader("Content-disposition", response.getHeader().get("Content-disposition"));
                    httpResponse.setHeader("Content-Length", response.getHeader().get("Content-Length"));
                    httpResponse.setHeader("Expires", "0");
                    InputStream in = response.getStream();
                    try(OutputStream out = httpResponse.getOutputStream()) {
                        int len = 0;
                        byte[] buffer = new byte[1024];
                        while ((len = in.read(buffer)) > 0) {
                            out.write(buffer,0,len);
                        }
                    }
                }
                return "{}";
            } else {
                throw new WxpnException(Json.toJson(response, JsonFormat.tidy()));
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
            throw new WxpnException("接口请求异常.");
        }
    }

    @Override
    public String delMaterialByMediaId(String token, String mediaId) {
        if (StringUtils.isEmpty(token)) {
            throw new WxpnException("用户授权Token不能为空");
        }
        if (StringUtils.isEmpty(mediaId)) {
            throw new WxpnException("素材媒体ID不能为空");
        }
        Map<String, Object> map = new HashMap<>(0);
        map.put("media_id", mediaId);
        try {
            Response response = Http.post3(Constant.DEL_MATERIAL + token, Json.toJson(map, JsonFormat.tidy()), Header.create().set("Content-Type", "application/json"), Constant.TIME_OUT, Constant.TIME_OUT);
            if (response.isOK()) {
                return FormaterUtils.defaultFormat(response.getContent("UTF-8"));
            } else {
                throw new WxpnException(Json.toJson(response, JsonFormat.tidy()));
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
            throw new WxpnException("接口请求异常.");
        }
    }
}
